package com.jinlia.show.modules.wxapp.service;

import com.alibaba.fastjson.JSONObject;
import com.jinlia.show.common.core.exception.MyRuntimeException;
import com.jinlia.show.common.core.utils.UserInfoUtils;
import com.jinlia.show.modules.base.constant.OrderPayStatusEnum;
import com.jinlia.show.modules.base.constant.PayForTypeEnum;
import com.jinlia.show.modules.base.constant.PayMethodTypeEnum;
import com.jinlia.show.modules.base.constant.PayResultStatusEnum;
import com.jinlia.show.modules.base.model.po.PayOrderPO;
import com.jinlia.show.modules.base.system.entity.DeliveryOrder;
import com.jinlia.show.modules.base.system.entity.MemberCard;
import com.jinlia.show.modules.base.system.entity.MemberCardBalanceChange;
import com.jinlia.show.modules.base.system.entity.Order;
import com.jinlia.show.modules.base.system.service.DeliveryOrderMapperService;
import com.jinlia.show.modules.base.system.service.MemberCardBalanceChangeMapperService;
import com.jinlia.show.modules.base.system.service.MemberCardMapperService;
import com.jinlia.show.modules.base.system.service.OrderMapperService;
import com.jinlia.show.modules.base.utils.PayOrderNumGenerator;
import com.jinlia.show.modules.base.wxapp.entity.MemberRechargeDiscount;
import com.jinlia.show.modules.base.wxapp.entity.PayOrder;
import com.jinlia.show.modules.base.wxapp.entity.PayOrderRecord;
import com.jinlia.show.modules.base.wxapp.entity.User;
import com.jinlia.show.modules.base.wxapp.service.MemberRechargeDiscountMapperService;
import com.jinlia.show.modules.base.wxapp.service.PayOrderMapperService;
import com.jinlia.show.modules.base.wxapp.service.PayOrderRecordMapperService;
import com.jinlia.show.modules.base.wxapp.service.UserMapperService;
import com.jinlia.show.modules.wxapp.websocket.WebSocketService;
import com.wechat.pay.java.service.partnerpayments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayWithRequestPaymentResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class PayService {

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderMapperService orderMapperService;
    @Autowired
    private DeliveryOrderMapperService deliveryOrderMapperService;
    @Autowired
    private WebSocketService webSocketService;
    @Autowired
    private UserMapperService userMapperService;
    @Autowired
    private MemberRechargeDiscountMapperService memberTopUpMapperService;
    @Autowired
    private MemberCardBalanceChangeMapperService memberCardBalanceChangeMapperService;
    @Autowired
    private PayOrderMapperService payOrderMapperService;
    @Autowired
    private PayOrderRecordMapperService payOrderRecordMapperService;
    @Autowired
    private MemberCardMapperService memberCardMapperService;
    @Autowired
    private RestTemplate wxRestTemplate;
//    @Autowired
//    private JsapiServiceExtension jsapiServiceExtension;
    @Autowired
    private PayOrderNumGenerator payOrderNumGenerator;

    /**
     * 支付提交
     *
     * @param payOrderPO
     * @return
     */
    @Transactional
    public PayOrder paySubmit(PayOrderPO payOrderPO) {
        PayOrder byIdPayOrder = payOrderMapperService.getById(payOrderPO.getId());
        List<PayOrderRecord> payOrderRecords = payOrderPO.getPayOrderRecords();
        payOrderRecords.forEach(i -> {//填充支付人
            i.setPayUserId(UserInfoUtils.getUserId());
            i.setPayUserName(UserInfoUtils.getUserName());
        });
        Order byIdOrder = orderMapperService.getById(byIdPayOrder.getPayForId());
        /**
         * 组合支付：最多两种，即余额+微信
         * 第一步：先处理余额支付
         * 第一步：处理微信支付
         */
        List<PayOrderRecord> balancePayList = payOrderRecords.stream().filter(item -> PayMethodTypeEnum.BALANCE_PAY.getValue().equals(item.getPayMethodType())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(balancePayList)) {
            //余额支付
            BigDecimal payAmount = balancePayList.get(0).getPayAmount();
            MemberCard byId = memberCardMapperService.getById(balancePayList.get(0).getMemberCardId());
            memberCardBalanceChangeMapperService.balancePayOrder(payOrderPO.getId(), payAmount, byId);
            byIdPayOrder.setPaidAmount(byIdPayOrder.getPayAmount().add(payAmount));
            balancePayList.get(0).setPayStatus(PayResultStatusEnum.SUCCESS.getValue());
            payOrderRecordMapperService.save(balancePayList.get(0));//创建支付记录
            byIdOrder.setReceivedMoney(byIdOrder.getReceivedMoney().add(payAmount));
        }
        //微信支付
        List<PayOrderRecord> wxPayList = payOrderRecords.stream().filter(item -> PayMethodTypeEnum.WX_PAY.getValue().equals(item.getPayMethodType())).collect(Collectors.toList());
        PayOrderRecord wxPayRecord = null;
        if (!CollectionUtils.isEmpty(wxPayList)) {
            wxPayRecord = wxPayList.get(0);
            wxPayRecord.setPayStatus(PayResultStatusEnum.USERPAYING.getValue());//用户支付中
            payOrderRecordMapperService.save(wxPayRecord);//创建支付记录
        }
        /**
         * 更新付款单状态和支付金额
         */
        if (byIdPayOrder.getPaidAmount().compareTo(BigDecimal.ZERO) == 0) {
            byIdPayOrder.setPayOrderStatus(OrderPayStatusEnum.UN_PAY.getValue());
        } else if (byIdPayOrder.getPaidAmount().compareTo(byIdPayOrder.getPayAmount()) < 0) {
            byIdPayOrder.setPayOrderStatus(OrderPayStatusEnum.PART_PAY.getValue());
        } else {
            byIdPayOrder.setPayOrderStatus(OrderPayStatusEnum.ALL_PAY.getValue());
        }
        payOrderMapperService.lambdaUpdate()
                .eq(PayOrder::getId, byIdPayOrder.getId())
                .set(PayOrder::getPaidAmount, byIdPayOrder.getPaidAmount())
                .set(PayOrder::getPayOrderStatus, byIdPayOrder.getPayOrderStatus())
                .update(new PayOrder());
        //---------------------------------------------------------订单处理------------------------------------------------------------------------
        /**
         * 更新付款单状态和支付金额
         */

        if (byIdOrder.getReceivedMoney().compareTo(BigDecimal.ZERO) == 0) {
            byIdOrder.setPayStatus(OrderPayStatusEnum.UN_PAY.getValue());//未支付
        } else if(byIdOrder.getReceivedMoney().compareTo(byIdOrder.getReceivableMoney()) < 0) {
            byIdOrder.setPayStatus(OrderPayStatusEnum.PART_PAY.getValue());//部分支付
        }else {
            byIdOrder.setPayStatus(OrderPayStatusEnum.ALL_PAY.getValue());//全部支付
        }
        orderMapperService.lambdaUpdate()
                .eq(Order::getId, byIdOrder.getId())
                .set(Order::getPayStatus, byIdOrder.getPayStatus())
                .set(Order::getReceivedMoney, byIdOrder.getReceivedMoney())
                .update(new Order());//更新订单状态
        //--------------------------------结算余额----------------------------------

        //发货状态 TODO 自动发货 (发货单模式)
        if (byIdOrder.getPayStatus().equals(OrderPayStatusEnum.ALL_PAY.getValue())) {//全部收款==> 自动发货
            DeliveryOrder deliveryOrder = new DeliveryOrder();
            deliveryOrder.setOrderId(byIdOrder.getId());
            deliveryOrderMapperService.waitConfirmDeliveryOrder(deliveryOrder);//待接单
        }
        //广播工作tai
        webSocketService.broadcastMsg("有新的订单生成!!!");
        return payOrderPO;
    }

    /**
     * 微信预支付订单
     * https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
     * https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
     * {
     * "mchid": "1900006XXX",
     * "out_trade_no": "1217752501201407033233368318",
     * "appid": "wxdace645e0bc2cXXX",
     * "description": "Image形象店-深圳腾大-QQ公仔",
     * "notify_url": "https://www.weixin.qq.com/wxpay/pay.php",
     * "amount": {
     * "total": 1,
     * "currency": "CNY"
     * },
     * "payer": {
     * "openid": "o4GgauInH_RCEdvrrNGrntXDuXXX"
     * }
     * }
     * prepay_id
     *
     * @param payOrderId
     * @return
     */
    public JSONObject payPre(Long payOrderId) {
        PayOrder byIdPayOrder = payOrderMapperService.getById(payOrderId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderId", payOrderId);//
        jsonObject.put("payOrderId", payOrderId);
        jsonObject.put("prepay_id", payOrderId); //微信支付id
        /**
         * 支付规则:
         * 1.优先余额支付
         * 1.余额不足 ==>组合支付
         */
        User byIdUser = userMapperService.getById(UserInfoUtils.getUserId());
        if (Objects.nonNull(byIdUser.getMemberCardId())) {
            MemberCard byIdMemberCard = memberCardMapperService.getById(byIdUser.getMemberCardId());
            if (byIdMemberCard.getBalance().compareTo(BigDecimal.ZERO) == 0) {
                //会员无余额==>全额支付
                jsonObject.put("payMoney", byIdPayOrder.getPayAmount());//微信付款
            } else if (byIdMemberCard.getBalance().compareTo(byIdPayOrder.getPayAmount()) >= 0) {
                //会员可全部支付==无需二次支付
                jsonObject.put("payMoney", BigDecimal.ZERO);//微信付款
                jsonObject.put("balancePay", byIdPayOrder.getPayAmount());//余额支付
                PayOrderPO payOrderPO = PayOrderPO.fromEntity(byIdPayOrder);
                PayOrderRecord payOrderRecord = new PayOrderRecord();
                payOrderRecord.setPayOrderId(payOrderPO.getId());
                payOrderRecord.setPayMethodType(PayMethodTypeEnum.BALANCE_PAY.getValue());
                payOrderRecord.setPayAmount(byIdPayOrder.getPayAmount());
                payOrderRecord.setPayUserId(UserInfoUtils.getUserId());
                payOrderRecord.setPayStatus(PayResultStatusEnum.SUCCESS.getValue());
                payOrderPO.setPayOrderRecords(Arrays.asList(payOrderRecord));
//                this.newPayOrder(payOrderPO);
            } else {
                //余额不足需二次支付
                BigDecimal bigDecimal = byIdPayOrder.getPayAmount().subtract(byIdMemberCard.getBalance()).setScale(2, RoundingMode.HALF_UP);
                jsonObject.put("payMoney", bigDecimal);//微信付款
                jsonObject.put("balancePay", byIdMemberCard.getBalance());//余额支付
            }

        } else {
            //无会员==>全额支付
            jsonObject.put("payMoney", byIdPayOrder.getPayAmount());
        }
        return jsonObject;
    }


    /**
     * 微信jsapi下单 :https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
     * 参数: {
     * * "mchid": "1900006XXX",
     * * "out_trade_no": "1217752501201407033233368318",
     * * "appid": "wxdace645e0bc2cXXX",
     * * "description": "Image形象店-深圳腾大-QQ公仔",
     * * "notify_url": "https://www.weixin.qq.com/wxpay/pay.php",
     * * "amount": {
     * * "total": 1,
     * * "currency": "CNY"
     * * },
     * * "payer": {
     * * "openid": "o4GgauInH_RCEdvrrNGrntXDuXXX"
     * * }
     * * }
     *
     * @param payOrder
     * @return
     */
    private String wxJsApiOrder(PayOrder payOrder) {
        JSONObject jsApiRequest = new JSONObject();
        jsApiRequest.put("mchid", "mchid");
        jsApiRequest.put("out_trade_no", payOrder.getId());
        jsApiRequest.put("appid", "appid");
        jsApiRequest.put("description", "青岛扎啤2*l");
        jsApiRequest.put("notify_url", "notify_url" + payOrder.getId());
        JSONObject amount = new JSONObject();
        amount.put("total", payOrder.getPayAmount());
        amount.put("currency", "CNY");
        jsApiRequest.put("amount", amount);
        ResponseEntity<JSONObject> wxRes =
                wxRestTemplate.postForEntity("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", jsApiRequest, JSONObject.class);
        log.info("微信预支付返回 = {}", wxRes.getBody().toJSONString());
        if (wxRes.getStatusCode().equals(HttpStatus.OK)) {
            JSONObject wxResBody = wxRes.getBody();
            return wxResBody.getString("prepay_id");
        }
        throw new MyRuntimeException("微信预支付失败");
    }

    //构造支付签名
    private String sign() {
        return "";
    }

    @Transactional
    public JSONObject payPreRecharge(Long memberRechargeDiscountId) {
        User byIdUser = userMapperService.getById(UserInfoUtils.getUserId());
        MemberRechargeDiscount byIdMemberRechargeDiscount = memberTopUpMapperService.getById(memberRechargeDiscountId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderId", byIdMemberRechargeDiscount.getId());
        jsonObject.put("payMoney", byIdMemberRechargeDiscount.getRechargeAmount());//充值金额
        //添加支付记录
        MemberCard byIdMemberCard = memberCardMapperService.getById(byIdUser.getMemberCardId());
        //生成支付单
        PayOrder byIdPayOrder = payOrderMapperService.createForMemberRecharge(byIdMemberCard, byIdMemberRechargeDiscount);
        jsonObject.put("payOrderId", byIdPayOrder.getId());
        //生成支付单 支付记录
        payOrderRecordMapperService.createByPayOrder(byIdPayOrder);
        return jsonObject;
    }

    /**
     * 余额充值
     *
     * @param payOrderId
     * @return
     */
    @Transactional
    public MemberCardBalanceChange payMemberBalance(Long payOrderId) {
        PayOrder payOrder = payOrderMapperService.getById(payOrderId);
        payOrder.setPaidAmount(payOrder.getPayAmount());
        //更新付款单
        payOrderMapperService.lambdaUpdate()
                .eq(PayOrder::getId, payOrderId)
                .set(PayOrder::getPaidAmount, payOrder.getPaidAmount())
                .set(PayOrder::getPayDate, LocalDate.now())
                .set(PayOrder::getPayDateTime, LocalDateTime.now())
                .set(PayOrder::getPayOrderStatus, OrderPayStatusEnum.ALL_PAY.getValue())
                .update(new PayOrder());

        //新增余额充值记录
        MemberCardBalanceChange memberCardBalanceChange = memberCardBalanceChangeMapperService.balanceRechargeByPayOrder(payOrder);
        //广播工作tai TODO
        webSocketService.broadcastMsg("有新的订单生成!!!");
        return memberCardBalanceChange;
    }

    public PayOrder payBySaleOrder(Long saleOrderId) {
        //获取该订单的付款带
        PayOrder one = payOrderMapperService.lambdaQuery()
                .eq(PayOrder::getPayForType, PayForTypeEnum.SALE.getValue())
                .eq(PayOrder::getPayForId, saleOrderId)
                .eq(PayOrder::getPayOrderStatus, OrderPayStatusEnum.UN_PAY.getValue())
                .one();
        if (one == null) {
            Order byIdOrder = orderMapperService.getById(saleOrderId);
            PayOrder payOrder = payOrderMapperService.createByOrder(byIdOrder);
            payOrder.setPayOrderNum(payOrderNumGenerator.nextId());
            payOrderMapperService.save(payOrder);
            return payOrder;
        }
        return one;
    }

    public List<PayOrder> getTodoList(PayOrder payOrder) {
        List<PayOrder> list = payOrderMapperService.lambdaQuery()
                .eq(Objects.nonNull(payOrder.getUserId()), PayOrder::getUserId, payOrder.getUserId())
                .list();
        return list;
    }

}
